package game.entities;

import game.level.Level;
import game.level.tiles.Tile;
import game.InputHandler;

public abstract class Mob extends Entity {

	protected String name;
	protected int speed;
	protected int numSteps = 0;
	protected boolean isMoving;
	protected int movingDir = 1;
	protected int velY;
	protected int velX;
	protected int numJumps = 0;
	protected int maxJump;
	protected boolean testbool;
	protected boolean felldown = false;
	protected int health;
	protected int maxHealth;
	protected int fallDmg;
	protected int fallSpdForDmg;
	protected boolean shouldTakeFallDmg = false;
	protected int pastVelY = 0;
	protected long lastTime = System.currentTimeMillis();
	protected int maxSpeed = 0;

	public Mob(Level level, String name, int x, int y, int speed, int maxSpeed) {
		super(level);
		this.name = name;
		this.x = x;
		this.y = y;
		this.speed = speed;
		this.hasHitbox = true;
		this.maxSpeed = maxSpeed;
	}

	public void move(int xa, int ya) {
		long thisTime = System.currentTimeMillis() + 100;
		numSteps++;
		if (true) {
			maxJump = 10;
		}
		if (!hasCollided(xa, ya) && xa != 0 && ya != 0) {
			if (ya < 0) {
				movingDir = 0;
			}
			if (ya > 0) {
				movingDir = 1;
			}
			if (xa < 0) {
				movingDir = 2;
			}
			if (xa > 0) {
				movingDir = 3;
			}
		}
		if (!hasCollided(xa, ya)) {
			if (xa != 0) {
				velX += xa;
				if (velX > 2) {
					velX--;
				}
				if (velX < -2) {
					velX++;
				}
			} else {
				if (velX > 0) {
					velX -= 1;
				} else if (velX < 0) {
					velX += 1;
				}
			}
		}
		if (hasCollided(xa, 0)) {
			velX = 0;
		}
		if (!hasCollided(0, 1)) {
			if (thisTime - lastTime >= 100) {
				velY += 1;
				lastTime = thisTime;
			}
			if (!felldown && velY > 0 && numJumps == 0) {
				numJumps++;
				felldown = true;
			}
		} else if (hasCollided(0, 1) && velY > 0) {
			if (shouldTakeFallDmg) {
				takeDamage((int) (80 * Math.log10(velY > pastVelY ? velY
						: pastVelY) - 55.917600346881504382900888422041));
				System.out.println(velY > pastVelY ? velY : pastVelY);
				shouldTakeFallDmg = false;
			}
			numJumps = 0;
			felldown = false;
			velY = 0;
		}
		pastVelY = velY;
		if (hasCollided(0, -1) && velY < 0) {
			y += 1;
			velY = 0;
		}
		if (numJumps < maxJump && ya == -1 && !testbool) {
			velY = -4;
			numJumps++;
			shouldTakeFallDmg = false;
		}
		testbool = Player.getHeldJump();
		if (velY > 20) {
			velY = 20;
		} else if (velY > this.fallSpdForDmg) {
			shouldTakeFallDmg = true;
		}
		int tempy = y;
		if (velY > 0) {
			for (int vel = 0; vel < velY; vel++) {
				y = tempy + vel;
				if (hasCollided(0, 1)) {
					velY = vel;
					break;
				}
			}
		} else if (velY < 0) {
			for (int vel = 0; vel > velY; vel--) {
				y = tempy + vel;
				if (hasCollided(0, -1)) {
					thisTime += 100;
					velY = vel;
					break;
				}
			}
		}
		int tempx = x;
		if (velX > 0) {
			for (int vel = 0; vel < velX; vel++) {
				x = tempx + vel;
				if (hasCollided(1, 0)) {
					velX = vel;
					break;
				}
			}
		} else if (velX < 0) {
			for (int vel = 0; vel > velX; vel--) {
				x = tempx + vel;
				if (hasCollided(-1, 0)) {
					velX = vel;
					break;
				}
			}
		}
		y = tempy + velY;
		x = tempx + velX;

	}

	public abstract boolean hasCollided(int xa, int ya);

	public String getName() {
		return name;
	}

	public int getNumSteps() {
		return numSteps;
	}

	public void setNumSteps(int numSteps) {
		this.numSteps = numSteps;
	}

	public boolean isMoving() {
		return isMoving;
	}

	public void setMoving(boolean isMoving) {
		this.isMoving = isMoving;
	}

	public int getMovingDir() {
		return movingDir;
	}

	public void setMovingDir(int movingDir) {
		this.movingDir = movingDir;
	}

	public void takeDamage(int dmg) {
		health -= dmg;
		// health -= (dmg - defense); would be a way to do def. could also pass
		// in a boolean shouldDefend, for armor piercing attacks.
		if (health <= dmg) {
			die();
		}
	}

	private void die() {

	}
}
